package com.atguigu.myssm.myspringmvc;

import com.atguigu.myssm.ioc.BeanFactory;
import com.atguigu.myssm.util.StringUtil;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.nio.charset.StandardCharsets;

@WebServlet("*.do")
public class DispatcherServlet extends ViewBaseServlet {

    //    private Map<String, Object> beanMap = new HashMap<>();
    private BeanFactory beanFactory;

    public DispatcherServlet() {

    }

    @Override
    public void init() throws ServletException {
        super.init();
        // 之前是在此主动创建IOC容器 现在优化为从application作用域获取
//        beanFactory = new ClassPathXmlApplicationContext();
        Object beanFactoryObj = getServletContext().getAttribute("beanFactory");
        if (beanFactoryObj != null) {
            beanFactory = (BeanFactory) beanFactoryObj;
        } else {
            throw new RuntimeException("ioc容器获取失败");
        }
    }

/*    @Override
    public void init() throws ServletException {
        super.init();
        InputStream inputStream = getClass().getClassLoader().getResourceAsStream("applicationContext.xml");
        try {
            // 创建documentBuilderFactory
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            // 创建documentBuilder
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
            // 创建Document
            Document document = documentBuilder.parse(inputStream);
            // 获取所有的bean节点
            NodeList beanNodeList = document.getElementsByTagName("bean");
            for (int i = 0; i < beanNodeList.getLength(); ++i) {
                // 元素节点
                Node beanNode = beanNodeList.item(i);
                if (beanNode.getNodeType() == Node.ELEMENT_NODE) {
                    Element beanElement = (Element) beanNode;
                    String beanId = beanElement.getAttribute("id");
                    String className = beanElement.getAttribute("class");
                    // 获取对应的Controller
                    Class controllerBeanClass = Class.forName(className);
                    Object beanObj = controllerBeanClass.newInstance();
//                    Method setServletContextMethod = controllerBeanClass.getDeclaredMethod("setServletContext", ServletContext.class);
                    // 初始化设置servletContext
//                    setServletContextMethod.invoke(beanObj, this.getServletContext());

//                    Field servletContext = controllerBeanClass.getDeclaredField("servletContext");
//                    servletContext.setAccessible(true);
//                    servletContext.set(beanObj, this.getServletContext());
                    beanMap.put(beanId, beanObj);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }*/

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding(StandardCharsets.UTF_8.toString());
        /*
        url: http://localhost:8080/web01/hello.do
        servletPath: /hello.do
        /hello.do -> hello
        hello -> HelloController
         */
        String servletPath = req.getServletPath();
//        System.out.println("servletPath = " + servletPath);
        servletPath = servletPath.substring(1);
        int lastDotIndex = servletPath.lastIndexOf(".do");
        servletPath = servletPath.substring(0, lastDotIndex);
//        System.out.println("servletPath = " + servletPath);
//        Object controllerBeanObj = beanMap.get(servletPath);
        Object controllerBeanObj = beanFactory.getBean(servletPath);

        String operate = req.getParameter("operate");
        if (StringUtil.isEmpty(operate)) {
            operate = "index";
        }

        Method[] methods = controllerBeanObj.getClass().getDeclaredMethods();
        for (Method method : methods) {
            // 获取方法名称
            String methodName = method.getName();
            if (operate.equals(methodName)) {
                // 统一获取请求参数
                // 获取当前方法的参数 返回参数数组
                Parameter[] parameters = method.getParameters();
                // parameterValues 存放参数值
                Object[] parameterValues = new Object[parameters.length];
                for (int i = 0; i < parameterValues.length; i++) {
                    Parameter parameter = parameters[i];
                    String parameterName = parameter.getName();
                    if ("request".equals(parameterName)) {
                        parameterValues[i] = req;
                    } else if ("response".equals(parameterName)) {
                        parameterValues[i] = resp;
                    } else if ("session".equals(parameterName)) {
                        parameterValues[i] = req.getSession();
                    } else {
                        // 从请求中获取参数值
                        String parameterValue = req.getParameter(parameterName);
                        String typeName = parameter.getType().getName();
                        Object parameterObj = parameterValue;
                        if (parameterObj != null && "java.lang.Integer".equals(typeName)) {
                            parameterObj = Integer.parseInt(parameterValue);
                        }
                        parameterValues[i] = parameterObj;
                    }

                }
                // controller组件方法调用
                method.setAccessible(true);
                // 执行方法
                Object returnObj = null;
                try {
                    returnObj = method.invoke(controllerBeanObj, parameterValues);
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new DispatcherServletException("DispatcherServlet出错了");
                }
                if (returnObj != null) {
                    // 视图处理
                    String methodReturnStr = (String) returnObj;
                    if (methodReturnStr.startsWith("redirect:")) {
                        String redirectStr = methodReturnStr.substring("redirect:".length());
                        resp.sendRedirect(redirectStr);
                    } else {
                        super.processTemplate(methodReturnStr, req, resp);
                    }
                }
                return;
            }
        }

/*        try {
            Method method = controllerBeanObj.
                    getClass().
                    getDeclaredMethod(operate, HttpServletRequest.class);
            if (method != null) {
                // 统一获取请求参数
                // 获取当前方法的参数 返回参数数组
                Parameter[] parameters = method.getParameters();

                // controller组件方法调用
                method.setAccessible(true);
                // 执行方法
                Object returnObj = method.invoke(controllerBeanObj, req);
                if (returnObj != null) {
                    // 视图处理
                    String methodReturnStr = (String) returnObj;
                    if (methodReturnStr.startsWith("redirect:")) {
                        String redirectStr = methodReturnStr.substring("redirect:".length());
                        resp.sendRedirect(redirectStr);
                    } else {
                        super.processTemplate(methodReturnStr, req, resp);
                    }
                }
                return;
            } else {
                throw new RuntimeException("operate参数错误");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }*/

    }
}
